home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / ldexp.cpp < prev    next >
C/C++ Source or Header  |  1992-02-04  |  6KB  |  278 lines

  1.  
  2. #if !defined (__M68881__) && !defined (sfp004)
  3.  
  4.  | add exponent to floating point number
  5.  | C Interface
  6.  | double ldexp(double value, unsigned int exp);
  7.  | returns value * 2**exp
  8.  | (int is 16 bits if -mshort, 32 bits if !-mshort)
  9.  |-----------------------------------------------------------------------------
  10.  | ported to 68000 by Kai-Uwe Bloem, 12/89
  11.  |  #1  original author: Peter S. Housel 9/21/88,01/17/89,03/19/89,5/24/89
  12.  |  #2    added support for denormalized numbers            -kub-, 01/90
  13.  |  #3  ported to gcc  ++jrb  04/90
  14.  |  #4  handle exponent overflow when ints are 32 bits        -kub-, 04/90
  15.  |-----------------------------------------------------------------------------
  16.  
  17.     .text; .even
  18.     .globl _ldexp
  19.     .globl __infinitydf
  20.  
  21. #ifdef    ERROR_CHECK
  22. _Overflow:
  23.     .ascii "ldexp: OVERFLOW\12\15\0"
  24.     .even
  25. #endif    ERROR_CHECK
  26.  
  27. _ldexp:
  28.     lea    sp@(4),a1
  29.     moveml    d2-d7,sp@-    | save d2-d7
  30.  
  31.     movew    a1@,d0        | extract value.exp
  32.     movew    d0,d2        | extract value.sign
  33.     lsrw    #4,d0
  34.     andw    #0x7ff,d0    | kill sign bit
  35.  
  36.     andw    #0x0f,a1@    | remove exponent from value.mantissa
  37.     tstw    d0        | check for zero exponent - no leading 1
  38.     beq    0f
  39.     orw    #0x10,a1@    | restore implied leading 1
  40.     bra    1f
  41. 0:    addw    #1,d0
  42. 1:
  43. #ifdef __MSHORT__
  44.     addw    a1@(8),d0    | add in exponent
  45.     extl    d0
  46. #else
  47.     extl    d0
  48.     addl    a1@(8),d0    | add in exponent
  49. #endif
  50.     cmpl    #-53,d0        | hmm. works only if 1 in implied position...
  51.     ble    retz        | range error - underflow
  52.     cmpl    #2047,d0
  53.     bge    rangerr        | range error - overflow
  54.  
  55.     clrw    d1        | zero rounding bits
  56.     moveml    a1@,d4-d5    | value into d4,d5
  57.     jmp    norm_df        | norm_df will pop d2-d7 and rts
  58.  
  59.  
  60.     .globl    _errno        | from <errno.h>
  61. ERANGE    =    63
  62.  
  63. retz:
  64.     moveq    #0,d0        | zero return value
  65.     moveq    #0,d1
  66.     jra    L0
  67.  
  68. rangerr:
  69.  
  70. #ifdef ERROR_CHECK
  71. # ifdef __MSHORT__
  72.     movew    #ERANGE,_errno    | set errno
  73. # else
  74.     movel    #ERANGE,_errno    | set errno
  75. # endif
  76.     moveml    d0-d1,a7@-
  77.     pea    _Overflow    | for printf
  78.     pea    __iob+52    |
  79.     jbsr    _fprintf    |
  80.     addql    #8,a7        |
  81.     moveml    a7@+,d0-d1
  82. #endif ERROR_CHECK
  83.  
  84.     moveml    __infinitydf,d0-d1 | return HUGE_VAL (same as in <math.h>)
  85.     andw    #0x8000,d2    | get sign bit of argument
  86.     swap    d2
  87.     clrw    d2
  88.     orl    d2,d0
  89. L0:
  90.     moveml    sp@+,d2-d7    | pop saved reggies
  91.     rts
  92.  
  93. #else    __M68881__ || sfp004
  94. #ifdef    __M68881__
  95. |#######################################################################
  96. |
  97. |# add exponent to floating point number
  98. |# C Interface
  99. |# double ldexp(double value, unsigned int exp);
  100. |# returns value * 2**exp
  101. |# (int is 16 bits if -mshort, 32 bits if !-mshort)
  102. |# performed entirely on the 68881 to avoid overfow as good as possible
  103. |##############################################################################
  104. |# hacked for the 68881 by Michael Ritzert, 5.10.90
  105. |##############################################################################
  106. |# ported fromt sfp004 to real coprocessor, mjr, August 1991
  107. |################################################################################
  108.  
  109.     .text; .even
  110.     .globl _ldexp
  111.  
  112. #ifdef    ERROR_CHECK
  113. _Domain:
  114.     .ascii "ldexp: NAN\12\15\0"
  115. _Overflow:
  116.     .ascii "ldexp: OVERFLOW\12\15\0"
  117.     .even
  118. double_max:
  119.     .long    0x7fee42d1
  120.     .long    0x30273b76
  121. double_min:
  122.     .long    0xffee42d1
  123.     .long    0x30273b76
  124. NaN:
  125.     .long    0x7fffffff
  126.     .long    0xffffffff
  127. p_Inf:
  128.     .long    0x7ff00000
  129.     .long    0x00000000
  130. m_Inf:
  131.     .long    0xfff00000
  132.     .long    0x00000000
  133. .even
  134. #endif    ERROR_CHECK
  135.  
  136. _ldexp:
  137.  
  138. #ifdef __MSHORT__
  139.     movew    a7@(12),d0        | get exponent
  140.     extl    d0
  141. #else
  142.     movel    a7@(12),d0        | get exponent
  143. #endif
  144.     fgetexpd a7@(4),fp1        | extract exponent of 1st arg
  145.     fmovel    fp1,d1            | d1 serves as accumulator
  146.     addl    d0,d1            | sum of exp_s of both args
  147.  
  148.     ftwotoxl d0,fp0            | ftwotox to fp0 (as long int!)
  149.     fmuld    a7@(4),fp0        | fmul value,fp0
  150.     fmoved    fp0,a7@-        | get double from fp0
  151.     moveml    a7@+,d0-d1
  152.  
  153. #endif  __M68881__
  154. #ifdef    sfp004
  155.  
  156. | add exponent to floating point number
  157. | C Interface
  158. | double ldexp(double value, unsigned int exp);
  159. | returns value * 2**exp
  160. | (int is 16 bits if -mshort, 32 bits if !-mshort)
  161. | performed entirely on the 68881 to avoid overfow as good as possible
  162. |
  163. | hacked for the 68881 by Michael Ritzert, 5.10.90
  164. |
  165.  
  166. | addresses of the 68881 data port. This choice is fastest when much data is
  167. | transferred between the two processors.
  168.  
  169. comm =     -6    |    fpu command reg
  170. resp =    -16    |    fpu response reg
  171. zahl =      0    |    fpu data reg
  172.  
  173. | waiting loop ...
  174. |
  175. | wait:
  176. | ww:    cmpiw    #0x8900,a1@(resp)
  177. |     beq    ww
  178. | is coded directly by
  179. |    .byte    0x0c,0x69,0x89,0x00,0xff,0xf0,0x67,0xf8 (a1)
  180. |    or
  181. |    .long    0x0c6889000, 0x000067f8            (a0)
  182.  
  183.     .text; .even
  184.     .globl _ldexp
  185.  
  186. #ifdef    ERROR_CHECK
  187. _Domain:
  188.     .ascii "ldexp: NAN\12\15\0"
  189. _Overflow:
  190.     .ascii "ldexp: OVERFLOW\12\15\0"
  191.     .even
  192. double_max:
  193.     .long    0x7fee42d1
  194.     .long    0x30273b76
  195. double_min:
  196.     .long    0xffee42d1
  197.     .long    0x30273b76
  198. NaN:
  199.     .long    0x7fffffff
  200.     .long    0xffffffff
  201. p_Inf:
  202.     .long    0x7ff00000
  203.     .long    0x00000000
  204. m_Inf:
  205.     .long    0xfff00000
  206.     .long    0x00000000
  207. .even
  208. #endif    ERROR_CHECK
  209.  
  210. _ldexp:
  211.     lea    0xfffa50,a0        | fpu address
  212.     movew    #0x4011,a0@(comm)    | ftwotox to fp0 (as long int!)
  213. #ifdef __MSHORT__
  214.     movew    a7@(12),d0        | get exponent
  215.     extl    d0
  216. #else
  217.     movel    a7@(12),d0        | get exponent
  218. #endif
  219.     cmpiw    #0x8900,a0@(resp)    | check if fpu is ready
  220.     movel    d0,a0@            | push arg
  221.     .long    0x0c6889000, 0xfff067f8    | wait
  222.     movew    #0x5423,a0@(comm)    | fmul value,fp0
  223.     .long    0x0c6889000, 0xfff067f8    | wait
  224.     movel    a7@(4),a0@        | load value
  225.     movel    a7@(8),a0@        |
  226.     .long    0x0c6889000, 0xfff067f8    | wait
  227.     movew    #0x7400,a0@(comm)    | get double from fp0
  228.     .long    0x0c6889000, 0xfff067f8    | wait
  229.     movel    a0@,d0
  230.     movel    a0@,d1
  231. #endif    sfp004
  232.  
  233. #ifdef    ERROR_CHECK
  234.     lea    double_max,a0    |
  235.     swap    d0        | exponent into lower word
  236.     cmpw    a0@(16),d0    | == NaN ?
  237.     beq    error_nan    |
  238.     cmpw    a0@(24),d0    | == + Infinity ?
  239.     beq    error_plus    |
  240.     swap    d0        | result ok,
  241.     rts            | restore d0
  242. # ifndef    __MSHORT__
  243. error_plus:
  244.     swap    d0
  245.     movel    #63,_errno    | Overflow: errno = ERANGE
  246.     moveml    d0-d1,a7@-    | print error message
  247.     pea    _Domain        | for printf
  248.     bra    error_exit    |
  249. error_nan:
  250.     moveml    a0@(24),d0-d1    | result = +inf
  251.     movel    #62,_errno    | NAN => errno = EDOM
  252.     moveml    d0-d1,a7@-    | print error message
  253.     pea    _Overflow    | for printf
  254. # else    __MSHORT__
  255. error_plus:
  256.     swap    d0
  257.     movew    #63,_errno    | Overflow: errno = ERANGE
  258.     moveml    d0-d1,a7@-    | print error message
  259.     pea    _Domain        | for printf
  260.     bra    error_exit    |
  261. error_nan:
  262.     moveml    a0@(24),d0-d1    | result = +inf
  263.     movew    #62,_errno    | NAN => errno = EDOM
  264.     moveml    d0-d1,a7@-    | print error message
  265.     pea    _Overflow    | for printf
  266. # endif    __MSHORT__
  267. error_exit:
  268.     pea    __iob+52    |
  269.     jbsr    _fprintf    |
  270.     addql    #8,a7        |
  271.     moveml    a7@+,d0-d1
  272.     rts
  273. #else    ERROR_CHECK
  274.     rts
  275. #endif    ERROR_CHECK
  276.  
  277. #endif    /* !__M68881__ && !sfp004    */
  278.